package com.yuanrui.circle.server.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yuanrui.circle.api.enums.IsDeletedFlagEnum;
import com.yuanrui.circle.api.req.GetShareCommentReq;
import com.yuanrui.circle.api.req.RemoveShareCommentReq;
import com.yuanrui.circle.api.req.SaveShareCommentReplyReq;
import com.yuanrui.circle.api.vo.ShareCommentReplyVO;
import com.yuanrui.circle.server.dao.ShareMomentDao;
import com.yuanrui.circle.server.entity.ShareCommentReply;
import com.yuanrui.circle.server.dao.ShareCommentReplyDao;
import com.yuanrui.circle.server.entity.ShareMoment;
import com.yuanrui.circle.server.entity.UserInfo;
import com.yuanrui.circle.server.rpc.UserRpc;
import com.yuanrui.circle.server.service.ShareCommentReplyService;
import com.yuanrui.circle.server.util.LoginUtil;
import com.yuanrui.circle.server.util.TreeUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;


/**
 * 评论及回复信息(ShareCommentReply)表服务实现类
 *
 * @author makejava
 * @since 2024-07-28 16:15:01
 */
@Service("shareCommentReplyService")
public class ShareCommentReplyServiceImpl extends ServiceImpl<ShareCommentReplyDao,ShareCommentReply> implements ShareCommentReplyService {
    @Resource
    private ShareCommentReplyDao shareCommentReplyDao;
    @Resource
    private ShareMomentDao shareMomentDao;
    @Resource
    private UserRpc userRpc;

    /**
     * 通过ID查询单条数据
     *
     * @param id 主键
     * @return 实例对象
     */
    @Override
    public ShareCommentReply queryById(Long id) {
        return this.shareCommentReplyDao.queryById(id);
    }

    /**
     * 分页查询
     *
     * @param shareCommentReply 筛选条件
     * @param pageRequest      分页对象
     * @return 查询结果
     */
    @Override
    public Page<ShareCommentReply> queryByPage(ShareCommentReply shareCommentReply, PageRequest pageRequest) {
        long total = this.shareCommentReplyDao.count(shareCommentReply);
        return new PageImpl<>(this.shareCommentReplyDao.queryAllByLimit(shareCommentReply, pageRequest), pageRequest, total);
    }

    /**
     * 新增数据
     *
     * @param shareCommentReply 实例对象
     * @return 实例对象
     */
    @Override
    public ShareCommentReply insert(ShareCommentReply shareCommentReply) {
        this.shareCommentReplyDao.insert(shareCommentReply);
        return shareCommentReply;
    }

    /**
     * 修改数据
     *
     * @param shareCommentReply 实例对象
     * @return 实例对象
     */
    @Override
    public ShareCommentReply update(ShareCommentReply shareCommentReply) {
        this.shareCommentReplyDao.update(shareCommentReply);
        return this.queryById(shareCommentReply.getId());
    }

    /**
     * 通过主键删除数据
     *
     * @param id 主键
     * @return 是否成功
     */
    @Override
    public boolean deleteById(Long id) {
        return this.shareCommentReplyDao.deleteById(id) > 0;
    }

    @Override
    public Boolean saveComment(SaveShareCommentReplyReq req) {
        ShareMoment shareMoment=shareMomentDao.selectById(req.getMomentId());
        ShareCommentReply shareCommentReply = new ShareCommentReply();
        shareCommentReply.setMomentId(req.getMomentId().intValue());
        shareCommentReply.setReplyType(req.getReplyType());
        String loginId = LoginUtil.getLoginId();
        //1.评论 2.回复
        if (req.getReplyType() == 1) {
            shareCommentReply.setParentId(-1L);
            shareCommentReply.setToId(req.getTargetId());
            shareCommentReply.setToUser(loginId);
            shareCommentReply.setToUserAuthor(Objects.nonNull(shareMoment.getCreatedBy()) && loginId.equals(shareMoment.getCreatedBy()) ? 1 : 0);
            addReplyCount(req.getMomentId(), 1);
        } else {
            shareCommentReply.setParentId(req.getTargetId());
            shareCommentReply.setToId(req.getTargetId());
            shareCommentReply.setToUser(loginId);
            shareCommentReply.setReplyId(req.getTargetId());
            shareCommentReply.setReplayAuthor(Objects.nonNull(shareMoment.getCreatedBy()) && loginId.equals(shareMoment.getCreatedBy()) ? 1 : 0);
            addReplyCount(req.getMomentId(), 1);
        }
        shareCommentReply.setContent(req.getContent());
        if (!CollectionUtils.isEmpty(req.getPicUrlList())) {
            shareCommentReply.setPicUrls(JSON.toJSONString(req.getPicUrlList()));
        }
        shareCommentReply.setCreatedBy(loginId);
        shareCommentReply.setCreatedTime(new Date());
        shareCommentReply.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode());
        shareMomentDao.incrReplyCount(shareCommentReply.getId(),1);
        return shareCommentReplyDao.insert(shareCommentReply) > 0;
    }

    private void addReplyCount(Long momentId, int i) {
        shareMomentDao.incrReplyCount(momentId, i);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean removeComment(RemoveShareCommentReq req) {
        ShareCommentReply comment = getById(req.getId());
        LambdaQueryWrapper<ShareCommentReply> query = Wrappers.<ShareCommentReply>lambdaQuery()
                .eq(ShareCommentReply::getMomentId, comment.getMomentId())
                .eq(ShareCommentReply::getIsDeleted, IsDeletedFlagEnum.UN_DELETED.getCode()).select(ShareCommentReply::getId,
                        ShareCommentReply::getMomentId,
                        ShareCommentReply::getReplyType,
                        ShareCommentReply::getContent,
                        ShareCommentReply::getPicUrls,
                        ShareCommentReply::getCreatedBy,
                        ShareCommentReply::getToUser,
                        ShareCommentReply::getParentId);
        List<ShareCommentReply> list = list(query);
        List<ShareCommentReply> replyList = new ArrayList<>();
        List<ShareCommentReply> tree = TreeUtils.buildTree(list);
        for (ShareCommentReply reply : tree) {
            TreeUtils.findAll(replyList, reply, req.getId());
        }
        // 关联子级对象及 moment 的回复数量
        Set<Long> ids = replyList.stream().map(ShareCommentReply::getId).collect(Collectors.toSet());
        LambdaUpdateWrapper<ShareCommentReply> update = Wrappers.<ShareCommentReply>lambdaUpdate()
                .eq(ShareCommentReply::getMomentId, comment.getMomentId())
                .in(ShareCommentReply::getId, ids);
        ShareCommentReply updateEntity = new ShareCommentReply();
        updateEntity.setIsDeleted(IsDeletedFlagEnum.DELETED.getCode());
        int count = getBaseMapper().update(updateEntity, update);
        shareMomentDao.incrReplyCount(comment.getMomentId().longValue(), -count);
        return true;
    }

    @Override
    public List<ShareCommentReplyVO> listComment(GetShareCommentReq req) {
        LambdaQueryWrapper<ShareCommentReply> query = Wrappers.<ShareCommentReply>lambdaQuery()
                .eq(ShareCommentReply::getMomentId, req.getId())
                .eq(ShareCommentReply::getIsDeleted, IsDeletedFlagEnum.UN_DELETED.getCode())
                .select(ShareCommentReply::getId,
                        ShareCommentReply::getMomentId,
                        ShareCommentReply::getReplyType,
                        ShareCommentReply::getContent,
                        ShareCommentReply::getPicUrls,
                        ShareCommentReply::getCreatedBy,
                        ShareCommentReply::getToUser,
                        ShareCommentReply::getCreatedTime,
                        ShareCommentReply::getParentId);
        List<ShareCommentReply> list = list(query);
        List<String> userNameList = list.stream().map(ShareCommentReply::getCreatedBy).distinct().collect(Collectors.toList());
        Map<String, UserInfo> userInfoMap = userRpc.batchGetUserInfo(userNameList);
        UserInfo defaultUser = new UserInfo();
        List<ShareCommentReplyVO> voList = list.stream().map(item -> {
            ShareCommentReplyVO vo = new ShareCommentReplyVO();
            vo.setId(item.getId());
            vo.setMomentId(Long.valueOf(item.getMomentId()));
            vo.setReplyType(item.getReplyType());
            vo.setContent(item.getContent());
            if (Objects.nonNull(item.getPicUrls())) {
                vo.setPicUrlList(JSONArray.parseArray(item.getPicUrls(), String.class));
            }
            if (item.getReplyType() == 2) {
                vo.setFromId(item.getCreatedBy());
                vo.setToId(item.getToUser());
            }
            vo.setParentId(item.getParentId());
            UserInfo user = userInfoMap.getOrDefault(item.getCreatedBy(), defaultUser);
            vo.setUserName(user.getNickName());
            vo.setAvatar(user.getAvatar());
            vo.setCreatedTime(item.getCreatedTime().getTime());
            return vo;
        }).collect(Collectors.toList());
        return TreeUtils.buildTree(voList);
    }
}
